﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Fundamental.Boxing
{
    internal interface IChangeBoxedPoint
    {
        void Change(int x, int y);
    }

    internal struct Point : IChangeBoxedPoint
    {
        private int m_x, m_y;

        public Point(int x, int y)
        {
            m_x = x;
            m_y = y;
        }

        public void Change(int x, int y)
        {
            m_x = x;
            m_y = y;
        }

        public override string ToString()
        {
            return string.Format("{0},{1}", m_x, m_y);
        }
    }

    internal class BoxingDemo
    {
        public void Launch()
        {
            Point p = new Point(1, 1);
            Console.WriteLine(p);

            p.Change(2, 2);
            Console.WriteLine(p);

            //Boxes p, a memory will be allocated on managed heap the size is equal to the size of the field,
            //plus "type object pointer" and "sync block index",
            //then fields of p will be copied to managed heap,
            //fianlly, the address of the object is returned.
            object o = p;
            Console.WriteLine(o);

            //Unbox o, unboxing is the process is obtaining the address of the boxed object,
            //actuall, unboxing is not the exactly opposite action of boxing.
            ((Point)o).Change(3, 3);
            Console.WriteLine(o);

            // Boxes p, changes the boxed object and discards it.
            ((IChangeBoxedPoint)p).Change(4, 4);
            Console.WriteLine(p);
            // Changes the boxed object and shows it
            ((IChangeBoxedPoint)o).Change(5, 5);
            Console.WriteLine(o);
        }
    }
}
